package entity.main;

import java.io.Serializable;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;

import org.joda.time.LocalDate;

import ui.CreateEditTaskDialog.TaskData;
import entity.general.MinTime;
import entity.main.Task.TaskType;

public class ObjectiveTaskManager implements Serializable 
{
	
	Map <String, Objective> objectivesByName = new HashMap<>();
	Map <String, Task> tasksByName = new HashMap<>(); 
	
	Objective defaultObjective; 
	
	public ObjectiveTaskManager()
	{
		Objective obj = new Objective("Other");
	 objectivesByName.put("Other", obj);
	 defaultObjective = obj;
	}
	
	public void addObjective(String name)
	{
		objectivesByName.put(name, new Objective(name));
	}

	public Set<Objective> getObjectives() {
		return new HashSet<>(objectivesByName.values());
	}
	
//	public Task(String name, Objective parentObjective, LocalDate startDate, String description, Time timePlanned) {	
//	public Task(String name, Objective parentObjective, LocalDate startDate, LocalDate deadline, String description, Time timePlanned) {

	public void addTaskWithoutDeadline(String name, TaskType type, LocalDate start,
			String description, MinTime timeToSpend) {
		checkTaskName(name);
		Task task = new Task(name, type, defaultObjective, start, description, timeToSpend);
		tasksByName.put(name, task);
	}

	public void addTaskWithoutDeadline(String name, TaskType type,  String parentObjectiveName, LocalDate start,
				String description, MinTime timeToSpend) {
		checkTaskName(name);
		Objective obj = ensureObjectiveIsInSet(parentObjectiveName);
		Task task = new Task(name, type, obj, start, description, timeToSpend);
		tasksByName.put(name, task);
	}

	public void addTaskWithDeadline(String name, TaskType type,  LocalDate start, LocalDate deadline,
			String description, MinTime timeToSpend) {
		checkTaskName(name);
		Task task = new Task(name, type, defaultObjective, start, deadline, description, timeToSpend);
		tasksByName.put(name, task);		
	}

	public void addTaskWithDeadline(String name, TaskType type,  String parentObjectiveName, LocalDate start, LocalDate deadline,
			String description, MinTime timeToSpend) {
		checkTaskName(name);
		Objective obj = ensureObjectiveIsInSet(parentObjectiveName);
		Task task = new Task(name, type, obj, start, deadline, description, timeToSpend);
		tasksByName.put(name, task);
	}

	private void checkTaskName(String name)
	{
		if(tasksByName.containsKey(name))
			throw new DuplicateTaskNameException(name);
	}
	

	public Set <Task> getTasks()
	{
		return new HashSet<>(tasksByName.values());
	}

	private Objective ensureObjectiveIsInSet(String name)
	{
		if(!objectivesByName.containsKey(name))
		{
			Objective obj = new Objective(name);
			objectivesByName.put(name, obj);
			return obj;
		}
		else
			return objectivesByName.get(name);
	}

	public void deleteTask(Task task) {
		if(tasksByName.containsKey(task.getName()))
		{
			tasksByName.remove(task.getName());
		}
		else
		{
			throw new RuntimeException("Do not have task " + task.getName());
		}
	}
	
	public boolean hasTaskName(String name)
	{
		return tasksByName.containsKey(name);
	}
	
	public Task getTaskByName(String name)
	{
		return tasksByName.get(name);
	}
	
	public void editTask(Task task, TaskData taskData)
	{
		System.out.println("Editing " + task.getName());
		if(!task.getName().equals(taskData.name))
		{
			if(hasTaskName(taskData.name))
			{
				throw new RuntimeException("Duplicate name " + taskData.name);
			}
		}
		tasksByName.remove(task.getName());
		task.setName(taskData.name);
		task.setDeadline(taskData.deadline);
		task.setDescription(taskData.description);
		task.setParentObjective(objectivesByName.get(taskData.categoryName));
		task.setTimePlanned(taskData.allotedTime);
		tasksByName.put(task.getName(), task);			
		System.out.println("Task now has name " + task.getName());
	}

	public void toggleTaskCompleted(Task task) {
		task.setCompleted(!task.isCompleted());
	}
}
